/* conio.h library for large systems - small embedded systems use clibrary.c instead */
#include "../interpreter.h"

#ifndef BUILTIN_MINI_STDLIB

#include <conio.h>
#include "pointerList.h"

#if 0
void ConioCgets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Pointer = cgets(Param[0]->Val->Pointer);
}

void ConioCputs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = cputs(Param[0]->Val->Pointer);
}
#endif

void ConioGetch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = getch();
}

void ConioGetche(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = getche();
}

void ConioKbhit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = kbhit();
}

void ConioPutch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = putch(Param[0]->Val->Integer);
}

void ConioUngetch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = ungetch(Param[0]->Val->Integer);
}

static PointerToPointerList * _list = NULL;


void _setCallback(void *key, void *value)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
	}
	setOrAddPointerToPointerList(_list,key,value);
}

void *_getCallback(void *key)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
	}
	return getPointerToPointerList(_list,key);
}

int ConioCallbackValue = 0;

extern void PicocParse(Picoc *pc, const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
extern struct ValueType IntType;

static Picoc *_pc = NULL;

int _callCallback(void *key)
{
	if(_list == NULL)
	{
		_list = newPointerToPointerList();
		return 0;
	}
	if (!VariableDefined(_pc, TableStrRegister(_pc, "__callback_value")))
		VariableDefinePlatformVar(_pc, NULL, "__callback_value", &_pc->IntType, (union AnyValue *)&ConioCallbackValue, TRUE);

	char buf[512];

	sprintf(buf, "__callback_value = %s();", (char*)_getCallback(key)); 

	PicocParse(_pc, "startup", buf, strlen(buf), TRUE, TRUE, FALSE);
	return ConioCallbackValue;
}

void ConioSetCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    _setCallback(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
}

void ConioGetCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Pointer = _getCallback(Param[0]->Val->Pointer);
}

void ConioCallCallback(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    ReturnValue->Val->Integer = _callCallback(Param[0]->Val->Pointer);
}

#if 1
void ConioHelp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) 
{
    struct IncludeLibrary * libList =  _pc->IncludeLibList;
	while(libList)
	{

		printf("//---------------------%s-------------------//\n", libList->IncludeName);
		struct LibraryFunction * funcList = libList->FuncList;
		int index = 0;
		if(funcList != NULL)
		{
			while(funcList[index].Prototype)
			{
				printf("%s\n", funcList[index].Prototype);
				index++;
				//if(index == 3){ break; }
			}
		}
		
		
		libList = libList->NextLib;
	}
}

#endif




/* all conio functions */
struct LibraryFunction ConioFunctions[] =
{
#if 0
    { ConioCgets,   "char * cgets(char *);" },
    { ConioCputs,   "int cputs(char *);" },
#endif
    { ConioGetch,   		"int getch();" },
    { ConioGetche,  		"int getche();" },
    { ConioKbhit,   		"int kbhit();" },
    { ConioPutch,   		"int putch(int);" },
    { ConioUngetch, 		"int ungetch(int);" },
    { ConioSetCallback, 	"void setCallback(void *, char *);" },
    { ConioGetCallback, 	"char* getCallback(void *);" },
    { ConioCallCallback, 	"int callCallback(void *);" },
    { ConioHelp, 			"void help(void);" },
    { NULL,         NULL }
};

static int ZeroValue = 0;


/* creates various system-dependent definitions */
void ConioSetupFunc(Picoc *pc)
{   

	_pc = pc;
		
    /* define NULL, TRUE and FALSE */
    if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
        VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE);
}


#endif

